package com.huanxing.cloud.order.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huanxing.cloud.common.core.constant.CommonConstants;
import com.huanxing.cloud.common.core.enums.MallErrorCodeEnum;
import com.huanxing.cloud.common.core.util.SnowflakeIdUtils;
import com.huanxing.cloud.common.security.handler.HxBusinessException;
import com.huanxing.cloud.order.api.constant.MallOrderConstants;
import com.huanxing.cloud.order.api.entity.MallConfigProperties;
import com.huanxing.cloud.order.api.entity.OrderInfo;
import com.huanxing.cloud.order.api.entity.OrderItem;
import com.huanxing.cloud.order.api.entity.OrderRefund;
import com.huanxing.cloud.order.api.enums.OrderItemEnum;
import com.huanxing.cloud.order.api.enums.OrderRefundEnum;
import com.huanxing.cloud.order.event.HxOrderRefundEvent;
import com.huanxing.cloud.order.mapper.OrderInfoMapper;
import com.huanxing.cloud.order.mapper.OrderItemMapper;
import com.huanxing.cloud.order.mapper.OrderRefundMapper;
import com.huanxing.cloud.order.service.IOrderRefundService;
import com.huanxing.cloud.pay.api.constants.PayConstants;
import com.huanxing.cloud.pay.api.dto.CreateRefundsReqDTO;
import com.huanxing.cloud.pay.api.remote.RemoteRefundService;
import lombok.AllArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 商城退款单
 *
 * @author lijx
 * @date 2022/5/31
 */
@Service
@AllArgsConstructor
public class OrderRefundServiceImpl extends ServiceImpl<OrderRefundMapper, OrderRefund> implements IOrderRefundService {

	private final OrderInfoMapper orderInfoMapper;

	private final OrderItemMapper orderItemMapper;

	private final MallConfigProperties mallConfigProperties;

	@DubboReference
	private final RemoteRefundService remoteRefundService;

	private final ApplicationEventPublisher applicationEventPublisher;

	@Override
	public IPage<OrderRefund> adminPage(Page page, OrderRefund orderRefund) {
		return baseMapper.selectAdminPage(page, orderRefund);
	}

	@Override
	public OrderRefund getRefundById(String id) {
		return baseMapper.selectRefundById(id);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean refund(OrderRefund orderRefund) {
		String id = orderRefund.getId();
		String status = orderRefund.getStatus();
		String refuseReason = orderRefund.getRefuseReason();
		orderRefund = baseMapper.selectById(id);
		if (ObjectUtil.isNull(orderRefund)) {
			throw new HxBusinessException("退款单不存在");
		}
		// 拒绝退款 修改子订单状态
		OrderItem orderItem = orderItemMapper.selectById(orderRefund.getOrderItemId());

		// 同意退货退款
		if (OrderRefundEnum.STATUS_11.getCode().equals(status) || OrderRefundEnum.STATUS_12.getCode().equals(status)) {
			// 退款金额大于0
			// if (orderRefund.getRefundAmount().compareTo(BigDecimal.ZERO) <= 0) {
			// throw new HxBusinessException("退款金额大于0");
			// }
			// 查询订单
			OrderInfo orderInfo = orderInfoMapper.selectById(orderRefund.getOrderId());
			if (!CommonConstants.YES.equals(orderInfo.getPayStatus())) {
				throw new HxBusinessException("订单未支付");
			}
			// 已支付订单 子订单状态正常
			if ((!OrderItemEnum.REFUNDING.getStatus().equals(orderItem.getStatus())
					&& !OrderItemEnum.GOODS_REFUNDING.getStatus().equals(orderItem.getStatus()))) {
				throw new HxBusinessException("状态错误");
			}

			orderRefund.setRefundTradeNo(SnowflakeIdUtils.refundOrderNo());
			orderRefund.setStatus(status);
			orderRefund.setRefuseReason(refuseReason);

			CreateRefundsReqDTO createRefundsReqDTO = new CreateRefundsReqDTO();
			createRefundsReqDTO.setRefundAmount(orderRefund.getRefundAmount());
			createRefundsReqDTO.setRefundTradeNo(orderRefund.getRefundTradeNo());
			createRefundsReqDTO.setNotifyUrl(mallConfigProperties.getNotifyDomain());
			createRefundsReqDTO.setOutTradeNo(orderInfo.getOrderNo());
			createRefundsReqDTO.setTotalAmount(orderInfo.getPaymentPrice());
			switch (orderInfo.getPaymentType()) {
				// 无需支付
				case MallOrderConstants.PAYMENT_TYPE_0 ->
					applicationEventPublisher.publishEvent(new HxOrderRefundEvent(this, orderRefund, orderItem));

				// 微信支付 = 微信退款
				case MallOrderConstants.PAYMENT_TYPE_1 -> {
					createRefundsReqDTO.setRefundType(PayConstants.WECHAT_REFUND);
					remoteRefundService.refunds(createRefundsReqDTO);
				}
				// 支付宝支付 = 支付宝退款
				case MallOrderConstants.PAYMENT_TYPE_2 -> {
					createRefundsReqDTO.setRefundType(PayConstants.ALIPAY_REFUND);
					remoteRefundService.refunds(createRefundsReqDTO);
				}
				default -> throw new HxBusinessException(MallErrorCodeEnum.ERROR_60005.getMsg());
			}

		}
		else if (OrderRefundEnum.STATUS_21.getCode().equals(status)
				|| OrderRefundEnum.STATUS_22.getCode().equals(status)) {

			orderItem.setStatus(OrderItemEnum.NORMAL.getStatus());
			orderItemMapper.updateById(orderItem);
		}
		else {
			throw new HxBusinessException("状态错误");
		}

		return super.updateById(orderRefund);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public OrderRefund saveRefund(OrderRefund orderRefund) {
		OrderItem orderItem = orderItemMapper.selectById(orderRefund.getOrderItemId());
		if (ObjectUtil.isNull(orderItem)) {
			throw new HxBusinessException("子订单不存在");
		}
		// 只有正常订单可申请退款
		if (OrderItemEnum.NORMAL.getStatus().equals(orderItem.getStatus())) {
			if (OrderRefundEnum.STATUS_1.getCode().equals(orderRefund.getStatus())) {
				orderItem.setStatus(OrderItemEnum.REFUNDING.getStatus());
			}
			else if (OrderRefundEnum.STATUS_2.getCode().equals(orderRefund.getStatus())) {
				orderItem.setStatus(OrderItemEnum.GOODS_REFUNDING.getStatus());
			}
			else {
				throw new HxBusinessException("退款状态错误");
			}
			orderRefund.setRefundAmount(orderItem.getPaymentPrice());
			orderRefund.setArrivalStatus(CommonConstants.NO);
			orderRefund.setOrderId(orderItem.getOrderId());
			orderRefund.setShopId(orderItem.getShopId());
			baseMapper.insert(orderRefund);
			orderItemMapper.updateById(orderItem);
		}
		return orderRefund;
	}

	@Override
	public IPage<OrderRefund> getPage(Page page, OrderRefund orderRefund) {
		return baseMapper.selectAdminPage(page, orderRefund);
	}

}
